Skip to content

Technical review: Document CSS if() function #39516

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

chrisdavidmills
Copy link
Contributor

@chrisdavidmills chrisdavidmills commented May 14, 2025

Description

Chrome supports the CSS if() function from version 137. See https://chromestatus.com/feature/6313805904347136.

This PR documents the new function. Specifically, it:

  • Adds an if() reference page (nearly done, just needs examples)
  • Adds if() to the CSS values and units module page
  • Adds if() to the CSS value functions ref page.

Motivation

Additional details

Related issues and pull requests

@chrisdavidmills chrisdavidmills requested a review from a team as a code owner May 14, 2025 13:32
@chrisdavidmills chrisdavidmills requested review from estelle and removed request for a team May 14, 2025 13:32
@github-actions github-actions bot added the Content:CSS Cascading Style Sheets docs label May 14, 2025
@chrisdavidmills chrisdavidmills marked this pull request as draft May 14, 2025 13:33
@chrisdavidmills chrisdavidmills removed the request for review from estelle May 14, 2025 13:33
@github-actions github-actions bot added the size/m [PR only] 51-500 LoC changed label May 14, 2025
@chrisdavidmills chrisdavidmills requested review from a team and estelle and removed request for a team and estelle May 14, 2025 13:33
Copy link
Contributor

github-actions bot commented May 14, 2025

Preview URLs

Flaws (3)

Note! 1 document with no flaws that don't need to be listed. 🎉

URL: /en-US/docs/Web/CSS/CSS_Values_and_Units
Title: CSS values and units
Flaw count: 1

  • macros:
    • Macro produces link /en-US/docs/Web/CSS/url which is a redirect

URL: /en-US/docs/Web/CSS/if
Title: if()
Flaw count: 2

  • macros:
    • Macro produces link /en-US/docs/Web/CSS/linear-gradient which is a redirect
  • unknown:
    • Parse error: Unexpected input

(comment last updated: 2025-05-21 15:29:45)

@github-actions github-actions bot added size/l [PR only] 501-1000 LoC changed and removed size/m [PR only] 51-500 LoC changed labels May 15, 2025
@chrisdavidmills chrisdavidmills marked this pull request as ready for review May 15, 2025 14:31
@chrisdavidmills chrisdavidmills changed the title Document CSS if() function Technical review: Document CSS if() function May 15, 2025
1. The `<if-condition>` expressions are evaluated, in the order they appear in the function.
2. The first `<if-condition>` that evaluates to true has its associated `<value>` returned.
3. If none of the provided `<if-condition>` expressions evaluate to true (or no `<if-condition> : <value>` pairs are provided), the `else` `<value>` will be returned, if an `else : <value>` pair is included.
4. If no `else : <value>` pair is included, nothing is returned.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This depends on the definition of "nothing". With no "true" conditions, <guaranteed-invalid> is returned, which would make background-image behave like unset.

Another definition of "nothing" could be an empty token sequence, e.g. if(else:).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I've tried changing this sentence to:

If no else : <value> pair is included, {{glossary("guaranteed-invalid")}} is returned.

As we have a nice little glossary entry that explains guaranteed-invalid. Does that work?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(in my next commit)


1. The `<if-condition>` expressions are evaluated, in the order they appear in the function.
2. The first `<if-condition>` that evaluates to true has its associated `<value>` returned.
3. If none of the provided `<if-condition>` expressions evaluate to true (or no `<if-condition> : <value>` pairs are provided), the `else` `<value>` will be returned, if an `else : <value>` pair is included.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sentence assumes that else is placed last, which may be a reasonable assumption/simplification.

But note that else is really just an <if-condition> that always evaluates to "true". It can appear wherever you want, and as many times as you want:

div {
  background-image: if(
    style(--scheme: ice): linear-gradient(to left, #caf0f8, white, #caf0f8);
    else: url("debug.png");
    style(--scheme: fire): linear-gradient(to left, #ffc971, white, #ffc971); /* Never considered */
    else: none  /* Never considered */
  );
}

This is mostly useless, except if you have a long/complicated if() which doesn't behave like you expect and you need to "debug" it.

MDN doesn't necessarily need to capture that, though. :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this is really useful. I've updated my description to make it clear that it is possible to put an else: value pair anywhere, but then added a new section to talk about you should mostly just have one at the end, except for in very specific circumstances, which is where your debug example comes in.

However, you can only set single property values at a time with `if()`, whereas `@container` queries can be used to set whole sets of rules. You can also only check for a single property value at a time with `if()`, and can't use `and`, `or`, or `not`. There is no way to do something like this:

```css
style(--scheme: dark or --scheme: very-dark): black;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this example. You can do if(style((--scheme: dark) or (--scheme: very-dark)): thing).

The text above talks about if() only being able to "set" a single property at a time. I assume this refers to the fact that since if() is a conditional in the value space, it exists in the value of a single property, but it's a bit confusing to read.

Maybe it's actually the example the text confusing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I've rewritten it, tested and included some and/or/not examples.

media(width < 700px): 0 auto;
```

This is really useful when you need to vary a single property value based on a media query result, however, you can't use complex media queries inside an `if()` statement (multiple queries connected via `and`, `or`, or `not` keywords). For such cases, a regular {{cssxref("@media")}} construct is needed. The two approaches are complementary, and have different uses.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I've updated this section to suit, and included and and or examples. However, I had real trouble getting a not example to work. I ended up trying many different permutations, for example

background-color: if(
  media(not (width < 500px)): blue
);

background-color: if(
  not media(width < 500px): blue
);

Can you help me find an example that works? Or, is this a bug?

supports(color): blue;
```

Feature queries are really useful inside `if()` statements when you need to vary a single property value based on support for a particular property: value combination. however, you can't use complex feature queries inside an `if()` statement (multiple queries connected via `and`, `or`, or `not` keywords). For such cases, a regular {{cssxref("@supports")}} construct is needed. The two approaches are complementary, and have different uses.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same applies here: you can use and/or/not.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, updated, and I've added some examples.

@chrisdavidmills chrisdavidmills requested a review from andruud May 21, 2025 15:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Content:CSS Cascading Style Sheets docs size/l [PR only] 501-1000 LoC changed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants